package com.qunar.train.mock.database;

import com.qunar.base.meerkat.dao.QueryDAO;

import org.apache.ibatis.session.RowBounds;
import org.mybatis.spring.support.SqlSessionDaoSupport;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author: xudong.tai
 * @since: 2018/6/21 Description: 数据库查询接口mock 修改记录: 1，2018/07/23, 数据结构修改，全部改为map，用于区分不同类的调用。
 **/
public class MockQueryDAO extends SqlSessionDaoSupport implements QueryDAO {
    //接口返回值数据结构定义,定义Map类型区分不同调用方。
    private Map<Object, Object> executeForObjectReturnMap = new HashMap<>();
    private Map<String, Map<String, Object>> executeForMapReturnMap = new HashMap<>();
    private Map<Object, Object[]> executeForObjectArrayReturnMapPstrobjclass = new HashMap<>();
    private Map<String, Map<String, Object>[]> executeForMapArrayReturnMapPstrobj = new HashMap<>();
    private Map<Object, Object[]> executeForObjectArrayReturnMapPstrobjclassintint = new HashMap<>();
    private Map<String, Map<String, Object>[]> executeForMapArrayReturnMapPstrobjintint = new HashMap<>();
    private Map<String, List<Object>> executeForObjectListReturnMapPstrobj = new HashMap<>();
    private Map<String, List<Map<String, Object>>> executeForMapListReturnMapPstrobj = new HashMap<>();
    private Map<String, List<Object>> executeForObjectListReturnMapPstrobjintint = new HashMap<>();
    private Map<String, List<Map<String, Object>>> executeForMapListReturnMapPstrobjintint = new HashMap<>();

    //构造函数，初始化数据放在这里
    public MockQueryDAO() {

    }

    public static ThreadLocal<MockQueryDAO> threadLocal = new ThreadLocal<>();

    public static MockQueryDAO getInstance() {
        if (threadLocal.get() == null) {
            threadLocal.set(new MockQueryDAO());
        }
        return threadLocal.get();
    }

    //对外暴露set接口，可以个性化mock返回值
    @Deprecated
    public static void setExecuteForObjectReturnValue(Class clazz, Object executeForObjectReturnValue) {
        getInstance().executeForObjectReturnMap.put(clazz, executeForObjectReturnValue);
    }

    public static void setExecuteForObjectReturnValue(String sqlId, Object executeForObjectReturnValue) {
        getInstance().executeForObjectReturnMap.put(sqlId, executeForObjectReturnValue);
    }

    public static void setExecuteForMapReturnValue(String sqlId, Map<String, Object> executeForMapReturnValue) {
        getInstance().executeForMapReturnMap.put(sqlId, executeForMapReturnValue);
    }

    @Deprecated
    public static void setExecuteForObjectArrayReturnValuePstrobjclass(Class clazz, Object[] executeForObjectArrayReturnValuePstrobjclass) {
        getInstance().executeForObjectArrayReturnMapPstrobjclass.put(clazz, executeForObjectArrayReturnValuePstrobjclass);
    }

    public static void setExecuteForObjectArrayReturnValuePstrobjclass(String sqlId, Object[] executeForObjectArrayReturnValuePstrobjclass) {
        getInstance().executeForObjectArrayReturnMapPstrobjclass.put(sqlId, executeForObjectArrayReturnValuePstrobjclass);
    }

    public static void setExecuteForMapArrayReturnValuePstrobj(String sqlId, Map<String, Object>[] executeForMapArrayReturnValuePstrobj) {
        getInstance().executeForMapArrayReturnMapPstrobj.put(sqlId, executeForMapArrayReturnValuePstrobj);
    }

    @Deprecated
    public static void setExecuteForObjectArrayReturnValuePstrobjclassintint(Class clazz, Object[] executeForObjectArrayReturnValuePstrobjclassintint) {
        getInstance().executeForObjectArrayReturnMapPstrobjclassintint.put(clazz, executeForObjectArrayReturnValuePstrobjclassintint);
    }

    public static void setExecuteForObjectArrayReturnValuePstrobjclassintint(String sqlId, Object[] executeForObjectArrayReturnValuePstrobjclassintint) {
        getInstance().executeForObjectArrayReturnMapPstrobjclassintint.put(sqlId, executeForObjectArrayReturnValuePstrobjclassintint);
    }

    public static void setExecuteForMapArrayReturnValuePstrobjintint(String sqlId, Map<String, Object>[] executeForMapArrayReturnValuePstrobjintint) {
        getInstance().executeForMapArrayReturnMapPstrobjintint.put(sqlId, executeForMapArrayReturnValuePstrobjintint);
    }

    public static void setExecuteForObjectListReturnValuePstrobj(String sqlId, List<Object> executeForObjectListReturnValuePstrobj) {
        getInstance().executeForObjectListReturnMapPstrobj.put(sqlId, executeForObjectListReturnValuePstrobj);
    }

    public static void setExecuteForMapListReturnValuePstrobj(String sqlId, List<Map<String, Object>> executeForMapListReturnValuePstrobj) {
        getInstance().executeForMapListReturnMapPstrobj.put(sqlId, executeForMapListReturnValuePstrobj);
    }

    public static void setExecuteForObjectListReturnValuePstrobjintint(String sqlId, List<Object> executeForObjectListReturnValuePstrobjintint) {
        getInstance().executeForObjectListReturnMapPstrobjintint.put(sqlId, executeForObjectListReturnValuePstrobjintint);
    }

    public static void setExecuteForMapListReturnValuePstrobjintint(String sqlId, List<Map<String, Object>> executeForMapListReturnValuePstrobjintint) {
        getInstance().executeForMapListReturnMapPstrobjintint.put(sqlId, executeForMapListReturnValuePstrobjintint);
    }


    //对接口函数进行实现，返回mock数据
    public <E> E executeForObject(String var1, Object var2, Class<E> var3) {
        this.getSqlSession().selectOne(var1, var2);

        if (getInstance().executeForObjectReturnMap.containsKey(var3)) {
            return (E) getInstance().executeForObjectReturnMap.get(var3);
        } else if (getInstance().executeForObjectReturnMap.containsKey(var1)) {
            return (E) getInstance().executeForObjectReturnMap.get(var1);
        } else {
            return null;
        }
    }

    public Map<String, Object> executeForMap(String var1, Object var2) {
        this.executeForObject(var1, var2, Map.class);

        if (getInstance().executeForMapReturnMap.containsKey(var1)) {
            return getInstance().executeForMapReturnMap.get(var1);
        } else {
            return null;
        }
    }

    public <E> E[] executeForObjectArray(String var1, Object var2, Class<E> var3) {
        this.getSqlSession().selectList(var1, var2);

        if (executeForObjectArrayReturnMapPstrobjclass.containsKey(var3)) {
            return (E[]) getInstance().executeForObjectArrayReturnMapPstrobjclass.get(var3);
        } else if (executeForObjectArrayReturnMapPstrobjclass.containsKey(var1)) {
            return (E[]) getInstance().executeForObjectArrayReturnMapPstrobjclass.get(var1);
        } else {
            return null;
        }
    }

    public Map<String, Object>[] executeForMapArray(String var1, Object var2) {
        this.executeForObjectArray(var1, var2, Map.class);

        if (getInstance().executeForMapArrayReturnMapPstrobj.containsKey(var1)) {
            return getInstance().executeForMapArrayReturnMapPstrobj.get(var1);
        } else {
            return null;
        }
    }

    public <E> E[] executeForObjectArray(String var1, Object var2, Class<E> var3, int var4, int var5) {
        this.getSqlSession().selectList(var1, var2, new RowBounds(var4, var5));

        if (getInstance().executeForObjectArrayReturnMapPstrobjclassintint.containsKey(var3)) {
            return (E[]) getInstance().executeForObjectArrayReturnMapPstrobjclassintint.get(var3);
        } else if (getInstance().executeForObjectArrayReturnMapPstrobjclassintint.containsKey(var1)) {
            return (E[]) getInstance().executeForObjectArrayReturnMapPstrobjclassintint.get(var1);
        } else {
            return null;
        }
    }

    public Map<String, Object>[] executeForMapArray(String var1, Object var2, int var3, int var4) {
        this.executeForObjectArray(var1, var2, Map.class, var3, var4);

        if (getInstance().executeForMapArrayReturnMapPstrobjintint.containsKey(var1)) {
            return getInstance().executeForMapArrayReturnMapPstrobjintint.get(var1);
        } else {
            return null;
        }

    }

    public <E> List<E> executeForObjectList(String var1, Object var2) {
        this.getSqlSession().selectList(var1, var2);

        if (getInstance().executeForObjectListReturnMapPstrobj.containsKey(var1)) {
            return (List<E>) getInstance().executeForObjectListReturnMapPstrobj.get(var1);
        } else {
            return null;
        }
    }

    public List<Map<String, Object>> executeForMapList(String var1, Object var2) {
        this.executeForObjectList(var1, var2);

        if (getInstance().executeForMapListReturnMapPstrobj.containsKey(var1)) {
            return getInstance().executeForMapListReturnMapPstrobj.get(var1);
        } else {
            return null;
        }
    }

    public <E> List<E> executeForObjectList(String var1, Object var2, int var3, int var4) {
        this.getSqlSession().selectList(var1, var2, new RowBounds(var3, var4));

        if (getInstance().executeForObjectListReturnMapPstrobjintint.containsKey(var1)) {
            return (List<E>) getInstance().executeForObjectListReturnMapPstrobjintint.get(var1);
        } else {
            return null;
        }
    }

    public List<Map<String, Object>> executeForMapList(String var1, Object var2, int var3, int var4) {
        this.executeForObjectList(var1, var2, var3, var4);

        if (getInstance().executeForMapListReturnMapPstrobjintint.containsKey(var1)) {
            return getInstance().executeForMapListReturnMapPstrobjintint.get(var1);
        } else {
            return null;
        }
    }

    public static void clear() {
        getInstance().executeForObjectReturnMap = new HashMap<>();
        getInstance().executeForMapReturnMap = new HashMap<>();
        getInstance().executeForObjectArrayReturnMapPstrobjclass = new HashMap<>();
        getInstance().executeForMapArrayReturnMapPstrobj = new HashMap<>();
        getInstance().executeForObjectArrayReturnMapPstrobjclassintint = new HashMap<>();
        getInstance().executeForMapArrayReturnMapPstrobjintint = new HashMap<>();
        getInstance().executeForObjectListReturnMapPstrobj = new HashMap<>();
        getInstance().executeForMapListReturnMapPstrobj = new HashMap<>();
        getInstance().executeForObjectListReturnMapPstrobjintint = new HashMap<>();
        getInstance().executeForMapListReturnMapPstrobjintint = new HashMap<>();
    }
}
